package org.example.service.impl;

import com.alibaba.fastjson.JSON;
import org.apache.commons.lang3.StringUtils;
import org.example.constants.CacheKey;
import org.example.enums.BizCodeEnum;
import org.example.exception.BizException;
import org.example.interceptor.LoginInterceptor;
import org.example.model.LoginUser;
import org.example.model.ProductDO;
import org.example.request.CartItemRequest;
import org.example.service.CartService;
import org.example.service.ProductService;
import org.example.vo.CartItemVO;
import org.example.vo.CartVO;
import org.example.vo.ProductVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.BoundHashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

@Service
public class CartServiceImpl implements CartService {

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private ProductService productService;

    /**
     * 加入到购物车
     */
    @Override
    public void addToCart(CartItemRequest cartItemRequest) {
        Long productId = cartItemRequest.getProductId();
        Integer buyNum = cartItemRequest.getBuyNum();
        //获取购物车
        BoundHashOperations<String, Object, Object> myCart = getMyCartOps();
        //获取具体的购物项
        Object cacheObj = myCart.get(productId);
        String result = "";
        if (cacheObj != null) {
            result = (String) cacheObj;
        }
        if (StringUtils.isBlank(result)) {
            //redis中无购物车则插入
            CartItemVO cartItemVO = new CartItemVO();
            ProductVO productVO = productService.findById(productId);
            if (productVO == null) {
                throw new BizException(BizCodeEnum.CART_FAIL);
            }
            cartItemVO.setProductId(productId);
            cartItemVO.setBuyNum(buyNum);
            cartItemVO.setAmount(productVO.getAmount());
            cartItemVO.setProductTitle(productVO.getTitle());
            cartItemVO.setProductImg(productVO.getCoverImg());
            //加入到redis中
            myCart.put(productId, JSON.toJSONString(cartItemVO));
        } else {
            //redis中有购物车时则调整数量
            CartItemVO cartItemVO = JSON.parseObject(result, CartItemVO.class);
            cartItemVO.setBuyNum(cartItemVO.getBuyNum() + buyNum);
            //加入到redis中
            myCart.put(productId, JSON.toJSONString(cartItemVO));
        }
    }

    /**
     * 清空购物车
     */
    @Override
    public void clearMyCart() {
        redisTemplate.delete(getCartKey());
    }

    /**
     * 查看我的购物车
     */
    @Override
    public CartVO findMyCart() {
        //是否查询最新价格，查出所有购物项
        List<CartItemVO> cartItemVOList = this.buildCartItem(false);
        CartVO cartVO = new CartVO();
        //由于其他3个都是自动计算，所以不用set
        cartVO.setCartItems(cartItemVOList);
        return cartVO;
    }

    /**
     * 根据购物车ID，删除购物车
     */
    @Override
    public void deleteCartById(Long productId) {
        BoundHashOperations<String, Object, Object> myCartOps = getMyCartOps();
        myCartOps.delete(productId);
    }

    /**
     * 更新购物车
     *
     * @param cartItemRequest
     */
    @Override
    public void updateCart(CartItemRequest cartItemRequest) {
        //获取购物车
        BoundHashOperations<String, Object, Object> myCart = getMyCartOps();
        //根据id获取购物项的JSON字符串
        Object cartObj = myCart.get(cartItemRequest.getProductId());
        if (cartObj == null) {
            throw new BizException(BizCodeEnum.CART_FAIL);
        }
        String obj = (String) cartObj;
        //反序列化：将字符串转为对象
        CartItemVO cartItemVO = JSON.parseObject(obj, CartItemVO.class);
        cartItemVO.setBuyNum(cartItemRequest.getBuyNum());
        //重新加入到Redis
        myCart.put(cartItemRequest.getProductId(), JSON.toJSONString(cartItemVO));
    }

    /**
     * 根据一些商品id查出购物项
     *
     * @param productIds
     * @return
     */
    @Override
    public List<CartItemVO> confirmOrderItem(List<Long> productIds) {
        //获取最新的购物项
        List<CartItemVO> cartItemVOList = this.buildCartItem(true);
        List<CartItemVO> resultList = cartItemVOList.stream().filter(obj -> {
            if (productIds.contains(obj.getProductId())) {
                this.deleteCartById(obj.getProductId());
                return true;
            }
            return false;
        }).collect(Collectors.toList());
        return resultList;
    }

    /**
     * 查出是否为最新的购物项
     */
    private List<CartItemVO> buildCartItem(boolean latest) {
        //获取购物车的Hash
        BoundHashOperations<String, Object, Object> myCartOps = this.getMyCartOps();
        //获取购物车的JSON数据
        List<Object> itemList = myCartOps.values();
        List<CartItemVO> cartItemVOList = new ArrayList<>();
        //提取购物车id用的集合
        List<Long> productIdList = new ArrayList<>();
        //将购物车一个一个地封装成CartItemVO
        if (!CollectionUtils.isEmpty(itemList)) {
            for (Object item : itemList) {
                //将JSON字符串转为CartItemVO
                CartItemVO cartItemVO = JSON.parseObject((String) item, CartItemVO.class);
                cartItemVOList.add(cartItemVO);
                productIdList.add(cartItemVO.getProductId());
            }
        }
        //查询最新的商品价格
        if (latest) {
            this.setProductLatestPrice(productIdList, cartItemVOList);
        }
        return cartItemVOList;
    }

    private void setProductLatestPrice(List<Long> productIdList, List<CartItemVO> cartItemVOList) {
        //批量查询最新的ProductVO
        List<ProductVO> productVOList = productService.findProductsByIdBatch(productIdList);
        //根据id，提取出productId:productVO的Map
        Map<Long, ProductVO> latestProduct = productVOList.stream().collect(Collectors.toMap(ProductVO::getId, Function.identity()));
        //重新赋值
        cartItemVOList.stream().forEach(item -> {
            ProductVO productVO = latestProduct.get(item.getProductId());
            item.setAmount(productVO.getAmount());
            item.setProductTitle(productVO.getTitle());
            item.setProductImg(productVO.getCoverImg());
        });
    }

    /**
     * 获取购物车的key
     */
    private String getCartKey() {
        //用户的id作为key
        Long userId = LoginInterceptor.threadLocal.get().getId();
        return String.format(CacheKey.CART_KEY, userId);
    }

    /**
     * 从Redis中获取我的购物车
     */
    private BoundHashOperations<String, Object, Object> getMyCartOps() {
        String cartKey = getCartKey();
        return redisTemplate.boundHashOps(cartKey);
    }

}
